/**
 * ━━━━━━神兽出没━━━━━━
 * 　　　┏┓　　　┏┓
 * 　　┏┛┻━━━┛┻┓
 * 　　┃　　　　　　　┃
 * 　　┃　　　━　　　┃
 * 　　┃　┳┛　┗┳　┃
 * 　　┃　　　　　　　┃
 * 　　┃　　　┻　　　┃
 * 　　┃　　　　　　　┃
 * 　　┗━┓　　　┏━┛
 * 　　　　┃　　　┃神兽保佑, 永无BUG!
 * 　　　　┃　　　┃Code is far away from bug with the animal protecting
 * 　　　　┃　　　┗━━━┓
 * 　　　　┃　　　　　　　┣┓
 * 　　　　┃　　　　　　　┏┛
 * 　　　　┗┓┓┏━┳┓┏┛
 * 　　　　　┃┫┫　┃┫┫
 * 　　　　　┗┻┛　┗┻┛
 * ━━━━━━感觉萌萌哒━━━━━━
 */
package com.zkgengkun.console.service.impl;

import com.google.common.collect.Maps;
import com.zkgengkun.console.service.AuthService;
import com.zkgengkun.console.service.UserService;
import com.zkgengkun.constant.LoginConstants;
import com.zkgengkun.constant.SysConstants;
import com.zkgengkun.domain.User;
import com.zkgengkun.support.json.Jacksons;
import com.zkgengkun.support.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.service.spi.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;

/**
 * @author gengshikun
 * @date 2017/3/13
 */
@Service("authService")
public class AuthServiceImpl implements AuthService {

    private static final Logger logger = LoggerFactory.getLogger(AuthServiceImpl.class);

    @Autowired
    private UserService userService;

    /**
     * 登录
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public Map<String, Object> login(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        Map<String, Object> result = Maps.newHashMap();
        result.put("status", Boolean.FALSE);

        String email = request.getParameter("email");
        String password = request.getParameter("password");

        //用户名或密码为空
        if (StringUtils.isBlank(email) || StringUtils.isBlank(password)) {
            result.put("code", LoginConstants.ERROR_CODE_0002);
            result.put("msg", LoginConstants.ERROR_CODE_0002_MSG);
        } else {
            User user = this.userService.getOneByEmailAndPassword(email, password);
            //用户名或密码错误
            if (null == user) {
                result.put("code", LoginConstants.ERROR_CODE_0001);
                result.put("msg", LoginConstants.ERROR_CODE_0001_MSG);
            } else {
                // 登录成功  设置登录状态
                Map<String, Object> loginResult = this.setRedisLoginSession(user.getUserId());

                this.afterLoginOperate(request, response, loginResult.get("loginToken").toString(), (User) loginResult.get("currentUser"));

                //设置登录结果
                result.put("status", Boolean.TRUE);
                result.put("currentUser", loginResult.get("currentUser"));
                result.put("loginToken", loginResult.get("loginToken"));
                result.put("returnUrl", URLDecoder.decode(request.getParameter("returnUrl"), SysConstants.URL_CHARSET));
            }
        }

        return result;
    }

    /**
     * 注册
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public Map<String, Object> regin(HttpServletRequest request, HttpServletResponse response) {

        Map<String, Object> result = Maps.newHashMap();
        result.put("status", Boolean.FALSE);

        //注册
        String email = request.getParameter("email");
        Boolean resultReg = this.processRegister(email, request); //发邮箱激活
        if (!resultReg) {
            result.put("code", LoginConstants.ERROR_CODE_0007);
            result.put("msg", LoginConstants.ERROR_CODE_0007_MSG);
        } else {
            result.put("status", Boolean.TRUE);
            result.put("msg", "注册邮件已发送邮箱, 请前往激活!");
        }

        return result;
    }

    /**
     * 激活
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public Map<String, Object> activate(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = Maps.newHashMap();
        result.put("status", Boolean.FALSE);

        //激活
        String email = request.getParameter("email"); //获取email
        String validateCode = request.getParameter("validateCode"); //激活码

        // 处理激活
        Boolean flag = Boolean.FALSE;
        try {
            flag = this.processActivate(email, validateCode);
        } catch (ServiceException e) {
            result.put("code", LoginConstants.ERROR_CODE_0012);
            result.put("msg", e.getMessage());
        }

        // 激活成功
        if (flag) {
            User user = this.userService.getOneByEmail(email);
            // 设置登录状态
            Map<String, Object> loginResult = this.setRedisLoginSession(user.getUserId());
            this.afterLoginOperate(request, response, loginResult.get("loginToken").toString(), (User) loginResult.get("currentUser"));

            result.put("returnUrl", request.getParameter("returnUrl"));
            result.put("status", Boolean.TRUE);
        }

        return result;
    }

    /**
     * 处理激活
     *
     * @param email
     * @param validateCode
     */
    ///传递激活码和email过来
    public Boolean processActivate(String email, String validateCode) throws ServiceException {

        Boolean result = Boolean.FALSE;

        //数据访问层，通过email获取用户信息
        User user = this.userService.getOneByEmail(email);
        //验证用户是否存在
        if (user != null) {
            //验证用户激活状态
            if (!user.getValidate()) { //没激活
                //验证链接是否过期
                if (System.currentTimeMillis() - user.getRegisterTime() < DateUtils.MILLIS_PER_MINUTE * 30) {
                    //验证激活码是否正确
                    if (StringUtils.equals(JedisUtil.getInstance().STRINGS.get("user:" + user.getUserId()), validateCode)) {
                        //激活成功， //并更新用户的激活状态，为已激活
                        this.userService.updateValidate(user.getUserId(), Boolean.TRUE);
                        JedisUtil.getInstance().KEYS.del("user:" + user.getUserId());
                        result = Boolean.TRUE;
                    } else {
                        throw new ServiceException("激活码不正确");
                    }
                } else {
                    throw new ServiceException("激活码已过期！");
                }
            } else {
                throw new ServiceException("邮箱已激活，请登录！");
            }
        } else {
            throw new ServiceException("该邮箱未注册（邮箱地址不存在）！");
        }
        return result;
    }

    /**
     * 处理注册
     *
     * @param email
     */
    private Boolean processRegister(String email, HttpServletRequest request) {
        User user = this.userService.getOneByEmail(email);
        if (user == null) {
            user = new User();
            user.setName(email);
            user.setPassword(UUIDUtils.random16UUID());
            user.setEmail(email);
            user.setName(email);
            user.setDeleteBoolean(Boolean.FALSE);
            user.setCreateTime(System.currentTimeMillis());
            user.setRegisterTime(System.currentTimeMillis());
            user.setValidate(Boolean.FALSE);

            this.userService.save(user); //保存注册信息

            ///如果处于安全，可以将激活码处理的更复杂点，这里我稍做简单处理
            JedisUtil.getInstance().STRINGS.setEx("user:" + user.getUserId(), 60 * 30, Md5Utils.MD5(email));

            ///邮件的内容
            StringBuffer sb = new StringBuffer("点击下面链接激活账号，30分钟生效，否则重新注册账号，链接只能使用一次，请尽快激活！<br>");
            sb.append(request.getScheme() + "://" + request.getHeader("host") + "/auth/activate?action=activate&email=");
            sb.append(email);
            sb.append("&validateCode=");
            sb.append(Md5Utils.MD5(email));
            sb.append("&returnUrl=");
            try {
                sb.append(URLDecoder.decode(request.getParameter("returnUrl"), SysConstants.URL_CHARSET));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            sb.append("<br>");
            sb.append("激活后, 使用改密码进行登录: ");
            sb.append("<span style='color:red;'>" + user.getPassword() + "</span>");

            //发送邮件
            SendEmailUtil.send(email, sb.toString());

            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }

    }

    /**
     * 退出登录
     *
     * @param response
     * @param request
     * @param user
     */
    @Override
    public void logout(HttpServletResponse response, HttpServletRequest request, User user) {
        String logoutToken = Md5Utils.MD5(LoginConstants.SALT + user.getUserId());
        JedisUtil.getInstance().KEYS.del(LoginConstants.CUSTOMER_LOGIN_REDIS_KEY + logoutToken);
        CookieUtils.deleteCookieByName(response, LoginConstants.CUSTOMER_LOGIN_TOKEN);
    }

    private Map<String, Object> reg(String username, String password) {
        Map<String, Object> result = Maps.newHashMap();
        result.put("status", Boolean.FALSE);

        //验证登录名和密码
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            result.put("code", LoginConstants.ERROR_CODE_0002);
            result.put("msg", LoginConstants.ERROR_CODE_0002_MSG);
            return result;
        }

        //验证用户登录名是否重复
        User user = this.userService.getOneByEmailAndPassword(username, password);

        if (null != user) {
            result.put("code", LoginConstants.ERROR_CODE_0007);
            result.put("msg", LoginConstants.ERROR_CODE_0007_MSG);
            return result;
        }

        //创建客户
        user = new User();
        user.setEmail(username);
        user.setPassword(password);
        user.setName(username);
        user.setCreateTime(System.currentTimeMillis());
        user.setDeleteBoolean(Boolean.FALSE);
        this.userService.save(user);

        //设置创建结果
        result.put("status", Boolean.TRUE);
        result.put("createUser", user);
        return result;
    }

    private void afterLoginOperate(HttpServletRequest request, HttpServletResponse response, String token, User currentUser) {
        //设置cookie
        CookieUtils.addCookie(response, LoginConstants.CUSTOMER_LOGIN_TOKEN, token, LoginConstants.CUSTOMER_LOGIN_OVER_TIME);
//        //cookie 购物车
//        List<CartItemVO> cookieCart = this.anonymousCartService.getCartFromCookie(request, CartConstants.CART_GROUP_MAIN_SITE);
//
//        //加载购物车
//        this.realNameCartApi.loadCartToRedis(currentUser.getCustomerId(), CartConstants.CART_GROUP_MAIN_SITE, cookieCart);
//
//        //删除cookie购物车
//        String cartKey = CartConstants.COOKIE_CART_KEY + "_" + CartConstants.CART_GROUP_MAIN_SITE;
//        CookieUtils.removeCookie(response, request, cartKey);
//
//        //登录日志
//        this.setLoginLog(request, currentUser, token);
    }

    private Map<String, Object> setRedisLoginSession(String userId) {
        Map<String, Object> resultMap = Maps.newHashMap();

        //登录token
        String loginToken = Md5Utils.MD5(LoginConstants.SALT + userId);
        User user = this.userService.getOneById(userId);
        logger.info(">>>>>>>>>>>>> redis value: {}", Jacksons.json().fromObjectToJson(user));
        JedisUtil.getInstance().STRINGS.setEx(LoginConstants.CUSTOMER_LOGIN_REDIS_KEY + loginToken,
                LoginConstants.CUSTOMER_LOGIN_OVER_TIME, Jacksons.json().fromObjectToJson(user));

        resultMap.put("loginToken", loginToken);
        resultMap.put("currentUser", user);

        return resultMap;
    }
}
